
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
//#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kern_levels.h>
/*linux内核中没有printf这个函数。printk相当于printf的孪生兄妹,printf运行在用户态，printk运行在内核态*/

static int character_device_major_number = 200;
static char readbuf[100] = "";/*读缓冲区*/
static char writebuf[100] = "";/*写缓冲区*/
static char kerneldata[] = {"kernel data!"};
const char character_device_name[32] = "character_device";
int number = 99;
/*模块参数允许用户在加载模块时通过命令行指定参数值*/
module_param(number,int,S_IRUGO);

/*打开设备*/
static int character_device_open(struct inode *inode,struct file *filp)
{
	printk("character_device open!\r\n");
	return 0;
}

/*从设备读取数据*/
static ssize_t character_device_read(struct file*filp , char __user *buf , size_t cnt , loff_t *offt)
{
	int ret = -1;
	/*向用户空间发送数据*/
	memcpy(readbuf,kerneldata,sizeof(kerneldata));
	ret = copy_to_user(buf,readbuf,cnt);
	if(ret == 0)
	{
		printk("kernel senddata ok!\r\n");		
	}else
	{
		printk("kernel sendata filed !\r\n");
	}
	printk("character device read ok!\r\n");
	return 0;
}

/*向设备写入数据*/
static ssize_t character_device_write(struct file*filp , const char __user *buf , size_t cnt , loff_t *offt)
{
	int ret = -1;
	/*接收用户空间传递给内核的数据并且打印出来*/
	ret = copy_from_user(writebuf,buf,cnt);
	if(ret == 0)
	{
		printk("kernel receivedata ok !,and data is %s\r\n",writebuf);		
	}else
	{
		printk("kernel receivedata filed !\r\n");
	}
	printk("character device write ok!\r\n");
	return 0;
}

/*释放设备*/
static int character_device_release(struct inode *inode,struct file *filp)
{
	printk("character device release!\r\n");
	return 0;
}
static struct file_operations character_device_fops = {
	.owner = THIS_MODULE,
	.open = character_device_open,
	.read = character_device_read,
	.write = character_device_write,
	.release = character_device_release,
}; 
static int character_device_init_module(void)
{   
	int ret = -1;
	/*注册字符设备驱动*/
	ret = register_chrdev(character_device_major_number,character_device_name,&character_device_fops);
	if(ret < 0)
	{
		printk(KERN_ERR"character device register failed!\r\n");
	}
	else
	{
		printk("character device register ok!\r\n");
	}
	printk("number = %d",number);
	return 0;
}

static void character_device_cleanup_module(void)
{   
	/*注销设备驱动*/
	unregister_chrdev(character_device_major_number,character_device_name);      
	printk("cleanup_module\r\n");

}

module_init(character_device_init_module);
module_exit(character_device_cleanup_module);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("liuzhanchang <15729296491@163.com> ");
MODULE_DESCRIPTION("a character device module");
